package econtract.util;


import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import econtract.simple.Contract;

public class ContractRepository{
	
	private File directory;
	private ArrayList<Contract> contracts;
	private String classesToBeBound;
	
	private ContractRepository(){
		contracts = new ArrayList<Contract>();
	}
	
	private void setClassesToBeBound(String c){
		classesToBeBound = c;
	}
	
	public List<Contract> getContracts(){
		return contracts;
	}
	
	public void setContracts(ArrayList<Contract> l){
		contracts = l;
	}
	
	public void addContract(Contract c){
		contracts.add(c);
	}
	
	public void setDirectory(File dir){
		directory = dir;
	}

	public File getDirectory(){
		return directory;
	}
	
	public int getSize(){
		return contracts.size();
	}
	
	public Contract getContract(String id){
		Contract r = null;
		for(Contract c : contracts){
			if(c.getHeader().getId().equalsIgnoreCase(id)){
				r = c;
				break;
			}
		}
		return r;
	}
	
	/**
	 * Reads a directory and loads all the contracts that match the contract schema.
	 * If the directory doesn't exist then an exception is thrown
	 * @param dir the contracts directory
	 * @return
	 */
	public static ContractRepository createInstance(String dir, String classesToBeBound) throws ContractRepositoryException{
		ContractRepository repo = new ContractRepository();
		File fDir = new File(dir);
		repo.setClassesToBeBound(classesToBeBound);
		if(fDir.isDirectory()){
			repo.setDirectory(fDir);
			repo.readContracts(fDir);
		}
		else {
			throw new ContractRepositoryException(dir);
		}
		return repo;
	}
	
	private void readContracts(File fDir){
        FilenameFilter filter = new FilenameFilter() {

                public boolean accept(File dir, String name) {
                    String[] tokens = name.split("[.]");
                    if(tokens[tokens.length-1].compareToIgnoreCase("xml")==0)
                            return true;
                    else return false;
                }
            };
            
	    try {
	    	JAXBContext jc = JAXBContext.newInstance(classesToBeBound);
			Unmarshaller um = jc.createUnmarshaller();
	
		    String[] files = fDir.list(filter);
		    for(int i = 0; i < files.length; i++){
		    	File c = new File(fDir+"\\"+files[i]);
		    	Contract r = (Contract) um.unmarshal(c);
		        contracts.add(r);
		    	}
			} catch (JAXBException e) {
				e.printStackTrace();		
			}		      
        }
	    
	public void saveContract(Contract c){
		try {
			String dir = directory.getAbsolutePath();
			JAXBContext jc = JAXBContext.newInstance("econtract.simple");
			Marshaller m = jc.createMarshaller();
			FileWriter file = new FileWriter(dir+"\\"+c.getHeader().getId()+".xml");
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			m.marshal(c, file);
			file.close();
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

